<?php

namespace App\VO\UserOrder\MetaInfo;

use App\BO\OrderStatus\OrderStateDefinition;
use App\BO\Product\ProductSkuInfoFactory;
use App\BO\PropertyAccessAndSetBO;
use App\BO\Order\OrderRemarkLabel\OrderRemarkLabel;
use App\Entities\CleanerEntity;
use App\Entities\CleanerModel;
use App\Entities\GoodsPaymentEntity;
use App\Entities\OrderCancelEntity;
use App\Entities\OrderEntity;
use App\Entities\OrderRefundEntity;
use App\Entities\OrderRemarkLabelRecordModel;
use App\Entities\OrderServiceInfoEntity;
use App\Entities\PaymentEntity;
use App\Entity\OrderServiceImageEntity;
use App\Utils\Assert;
use App\Utils\MoneyFormatUtil;
use App\VO\UserOrder\Adapter\CRMRefundStatusDescAdapter;

class UserOrderFactory
{
    /**
     * 订单详情
     * @param OrderEntity $orderEntity
     * @return OrderInfo
     * @throws \Exception
     */
    public static function getOrderInfo(OrderEntity $orderEntity)
    {
        $orderInfo = new OrderInfo();

        $orderBaseInfo = self::createOrderInfo($orderEntity);
        $orderInfo->setOrder($orderBaseInfo);

        $productInfo = self::createProductInfo($orderEntity);
        $orderInfo->setProduct($productInfo);

        $paymentInfo = self::createPaymentInfo($orderEntity);
        $orderInfo->setPayment($paymentInfo);

        $orderState = $orderEntity->getOrderState();
        switch ($orderState) {
            case OrderStateDefinition::STATE_WAITING_SERVICE:
            case OrderStateDefinition::STATE_WAITING_COMMENT:
                $serviceInfo = self::createServiceInfo($orderEntity);
                $orderInfo->setService($serviceInfo);
                break;
            case OrderStateDefinition::STATE_REFUND_WAITING_CHECK:
            case OrderStateDefinition::STATE_REFUND_WAITING_THIRD_PART_NOTIFY:
            case OrderStateDefinition::STATE_REFUND_SUCCESS:
                $serviceInfo = self::createServiceInfo($orderEntity);
                $orderInfo->setService($serviceInfo);
                $refundInfo = self::createRefundInfo($orderEntity);
                $orderInfo->setRefund($refundInfo);
                break;
            case OrderStateDefinition::STATE_USER_CANCEL:
                $cancelInfo = self::createCancelInfo($orderEntity);
                if (!is_null($cancelInfo)) {
                    $orderInfo->setCancel($cancelInfo);
                }
                break;
        }

        return $orderInfo;
    }

    /**
     * 评价页面
     * @param OrderEntity $orderEntity
     * @return OrderInfo
     * @throws \Exception
     */
    public static function getOrderCommentInfo(OrderEntity $orderEntity)
    {
        $commentInfo = new UserOrderCommentInfo();

        $label = OrderRemarkLabel::getReviewLabels();
        $commentInfo->setLabels($label);

        $title = OrderRemarkLabel::getStarsTitle();
        $commentInfo->setStarsTitle($title);
        return $commentInfo;
    }

    /**
     * 订单列表详情
     * @param OrderEntity $orderEntity
     * @return OrderListInfo
     * @throws \Exception
     */
    public static function getOrderListInfo(OrderEntity $orderEntity)
    {
        $orderInfo = new OrderListInfo();

        $orderBaseInfo = self::createOrderInfo($orderEntity);
        $orderInfo->setOrder($orderBaseInfo);

        $productInfo = self::createProductInfo($orderEntity);
        $orderInfo->setProduct($productInfo);

        return $orderInfo;
    }

    /**
     * @param OrderEntity $orderEntity
     * @return OrderBaseInfo
     * @throws \Exception
     */
    private static function createOrderInfo(OrderEntity $orderEntity)
    {
        $orderInfo = new OrderBaseInfo();

        PropertyAccessAndSetBO::sync($orderEntity, $orderInfo, PropertyAccessAndSetBO::getKeys($orderInfo));
        $orderInfo->setAddress($orderEntity->getFullAddress());

        $goodsPaymentEntity = GoodsPaymentEntity::findByTradeNo($orderEntity->getNo());
        Assert::notNull($goodsPaymentEntity);

        $orderInfo->setNum($goodsPaymentEntity->getNum());
        $orderInfo->setDiscountValue(MoneyFormatUtil::pennyToDollar($goodsPaymentEntity->getCouponDiscountValue()
            + $goodsPaymentEntity->getUseBalance() + $goodsPaymentEntity->getConvertibleCardDiscountValue()));
        $orderInfo->setCouponDiscountValue(MoneyFormatUtil::pennyToDollar($goodsPaymentEntity->getCouponDiscountValue()));
        $orderInfo->setBalanceDiscountValue(MoneyFormatUtil::pennyToDollar($goodsPaymentEntity->getUseBalance()));
        $orderInfo->setConvertibleCardDiscountValue(MoneyFormatUtil::pennyToDollar($goodsPaymentEntity->getConvertibleCardDiscountValue()));

        if ($goodsPaymentEntity->getConvertibleCardDiscountValue() > 0) {
            $orderInfo->setUseConvertibleCard(true);
        }

        if ($goodsPaymentEntity->getCouponDiscountValue() > 0) {
            $orderInfo->setUseCoupon(true);
        }

        $orderInfo->setOrderAmount(MoneyFormatUtil::dollarAddDollar($orderInfo->getTotalAmount(), $orderInfo->getDiscountValue()));

        $remarkLabels = OrderRemarkLabelRecordModel::select('content')->where('order_id', $orderEntity->getId())->get()
            ->toArray();
        if (!empty($remarkLabels)) {
            $orderInfo->setRemarkLabelContent($remarkLabels);
        }

        $stateDes = OrderStateDefinition::getDescByState($orderEntity->getOrderState());
        $orderInfo->setOrderStateDes($stateDes);

        return $orderInfo;
    }

    /**
     * @param OrderEntity $orderEntity
     * @return ServiceInfo
     */
    private static function createServiceInfo(OrderEntity $orderEntity)
    {
        $serviceInfo = new ServiceInfo();

        $serviceInfo->setCleanerName($orderEntity->getBnames());
        $serviceInfo->setServiceFinishDate($orderEntity->getCompletionTime());


        $cleanerEntity = CleanerEntity::find($orderEntity->getBids());
        if ($cleanerEntity) {
            $serviceInfo->setCleanerName($cleanerEntity->getRealName());
            $serviceInfo->setPhone($cleanerEntity->getPhone());
            $serviceInfo->setGender($cleanerEntity->getGender() == CleanerModel::GENDER_MALE ? '男' : '女');
        }

        $orderServiceInfoEntity = OrderServiceInfoEntity::findByOrderId($orderEntity->getId());
        if ($orderServiceInfoEntity) {
            $serviceInfo->setStartTime($orderServiceInfoEntity->getServiceStart());
            $serviceInfo->setEndTime($orderServiceInfoEntity->getServiceFinish());
            $serviceInfo->setServiceFinishDate($orderServiceInfoEntity->getServiceFinish());

            // 服务完成时上传的图片
            $images = OrderServiceImageEntity::getImagesByOrderId($orderEntity->getId());
            $serviceInfo->setServiceImages($images);
        }

        return $serviceInfo;
    }

    /**
     * @param OrderEntity $orderEntity
     * @return ProductInfo
     * @throws \Exception
     */
    private static function createProductInfo(OrderEntity $orderEntity)
    {
        $productSkuInfo = ProductSkuInfoFactory::getProductSkuInfo($orderEntity->getProductSkuId());

        /** * @var ProductInfo $info */
        $info = PropertyAccessAndSetBO::sync($productSkuInfo, new ProductInfo());
        return $info;
    }

    /**
     * @param OrderEntity $orderEntity
     * @return PaymentInfo
     * @throws \Exception
     */
    protected static function createPaymentInfo(OrderEntity $orderEntity)
    {
        $paymentEntity = PaymentEntity::findByTradeNo($orderEntity->getNo());
        Assert::notNull($paymentEntity);

        /** * @var PaymentInfo $paymentInfo */
        $paymentInfo = PropertyAccessAndSetBO::sync($paymentEntity, new PaymentInfo());
        $paymentInfo->setAmount(MoneyFormatUtil::pennyToDollar($paymentEntity->getAmount()));

        return $paymentInfo;
    }

    private static function createRefundInfo(OrderEntity $orderEntity)
    {
        $orderRefundEntity = OrderRefundEntity::findByOrderId($orderEntity->getId());
        Assert::notNull($orderRefundEntity);

        // 设置退款信息
        $refundInfo = new RefundInfo();
        $refundInfo->setOrderRefundId($orderRefundEntity->getId());
        $refundInfo->setType($orderRefundEntity->getType());
        $refundInfo->setRefundNo($orderRefundEntity->getRefundNo());
        $refundInfo->setReason($orderRefundEntity->getNote());
        $refundInfo->setPaymentMethod($orderRefundEntity->getPaymentMethod());
        $refundInfo->setRefundAt($orderRefundEntity->getRefundAt());
        $refundInfo->setCreatedAt($orderRefundEntity->getCreatedAt());
        $refundInfo->setState(
            (new CRMRefundStatusDescAdapter($orderRefundEntity->getRefundStatus()))->getDesc()
        );
        return $refundInfo;
    }

    /**
     * @param OrderEntity $orderEntity
     * @return CancelInfo|null
     */
    private static function createCancelInfo(OrderEntity $orderEntity)
    {
        $orderCancelEntity = OrderCancelEntity::findByOrderId($orderEntity->getId());
        if (is_null($orderCancelEntity)) {
            return null;
        }

        $cancelInfo = new CancelInfo();
        $cancelInfo->setReason($orderCancelEntity->getReason());

        return $cancelInfo;
    }
}
